package com.sak.vis.service;

import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;

import org.htmlcleaner.CleanerProperties;
import org.htmlcleaner.HtmlCleaner;
import org.htmlcleaner.TagNode;
import org.htmlcleaner.XPatherException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.sak.vis.domain.Result;

/**
 * onyomo.com implementation for the {@link ExternalClientService}.
 * 
 * @author Saket Vishal
 * 
 */
@Service(value = "onYoMoExternalClientService")
public class OnYoMoExternalClientServiceImpl extends
		GeneralExternalClientServiceImpl implements ExternalClientService {

	private static final String URL_ONYOMO = "http://www.onyomo.com/";

	private static final Logger logger = LoggerFactory
			.getLogger(OnYoMoExternalClientServiceImpl.class);
	
	/*@Value("#{appProperties['onyomo.url']}")
	private String onyomoURL;*/

	private static final String CARD_XPATH = "//div[@class='vcard record']";
	private static final String CARD_ITEM_ORG_NAME_XPATH = "div[@class='item']//a[@class='fn org']";
	private static final String CARD_ITEM_ADRESS_XPATH = "//span[@class='adr']//span";
	private static final String CARD_ITEM_PHONE_XPATH = "//span[@class='tel']";

	@Override
	public List<Result> queryClient(String queryText, String location) {
		URL url;
		TagNode node = null;
		HtmlCleaner cleaner = setupCleaner();
		try {
			url = new URL(URL_ONYOMO + queryText);
			URLConnection conn = url.openConnection();
			node = cleaner.clean(new InputStreamReader(conn.getInputStream()));
		} catch (MalformedURLException e) {
			logger.error("Problem in URL with queryText: " + queryText, e);
		} catch (IOException e) {
			logger.error("Problem reading from URL with queryText: "
					+ queryText, e);
		}

		List<Result> results = new ArrayList<Result>(5);

		if (node != null) {
			try {
				Object[] resultNodes = node.evaluateXPath(CARD_XPATH);
				if (resultNodes != null) {
					for (int i = 0; i < resultNodes.length && i < MAX_RESULTS; i++) {
						TagNode resultNode = (TagNode) resultNodes[i];

						String title = extractTitle(resultNode);
						String address = extractAddress(resultNode);
						String phone = extractPhone(resultNode);

						results.add(new Result(title, address, phone));
					}
				}

			} catch (XPatherException e) {
				logger.error("Failed in extraction with queryText: "
						+ queryText, e);
			}
		}
		return results;
	}

	private HtmlCleaner setupCleaner() {
		HtmlCleaner cleaner = new HtmlCleaner();

		CleanerProperties props = cleaner.getProperties();
		props.setAllowHtmlInsideAttributes(true);
		props.setAllowMultiWordAttributes(true);
		props.setRecognizeUnicodeChars(true);
		props.setOmitComments(true);
		return cleaner;
	}

	private String extractPhone(TagNode resultNode) throws XPatherException {
		String phone = "";
		Object[] phoneNodes = resultNode.evaluateXPath(CARD_ITEM_PHONE_XPATH);
		if (phoneNodes != null && phoneNodes.length > 0) {
			TagNode phoneNode = (TagNode) phoneNodes[0];
			phone = phoneNode.getText().toString();
		}
		return phone;
	}

	private String extractAddress(TagNode resultNode) throws XPatherException {
		String address = "";
		Object[] addressNodes = resultNode
				.evaluateXPath(CARD_ITEM_ADRESS_XPATH);
		if (addressNodes != null && addressNodes.length > 0) {
			StringBuilder addressBuilder = new StringBuilder();
			for (int j = 0; j < addressNodes.length; j++) {
				TagNode addressNode = (TagNode) addressNodes[j];
				addressBuilder.append(addressNode.getText() + " ");
			}
			address = addressBuilder.toString();
		}
		return address;
	}

	private String extractTitle(TagNode resultNode) throws XPatherException {
		String title = "";
		Object[] organisationNode = resultNode
				.evaluateXPath(CARD_ITEM_ORG_NAME_XPATH);
		if (organisationNode != null && organisationNode.length > 0) {
			TagNode orgNode = (TagNode) organisationNode[0];
			title = orgNode.getText().toString();
		}
		return title;
	}
}